package pr2.cromosoma;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CromosomaPVC extends Cromosoma<CromosomaPVC> {

    private List<Integer> genes;

    public CromosomaPVC() {
        this(true);
    }

    private CromosomaPVC(boolean inicializa) {

        this.genes = new ArrayList<Integer>(Distancias.CIUDADES.length);

        if (inicializa) {

            List<Integer> numeros = new ArrayList<Integer>(
                    Distancias.CIUDADES.length - 1);
            for (int i = 1; i < Distancias.getSize(); i++) {
                numeros.add(i);
            }

            // Siempre comienzo desde Madrid
            genes.add(0);

            while (numeros.size() > 0) {
                int i = new Double(Math.random() * numeros.size()).intValue();
                genes.add(numeros.get(i));
                numeros.remove(i);
            }

            this.setAdaptacion(evalua());

        }

    }

    public List<Integer> getGenes() {
        return genes;
    }

    @Override
    public List<Integer> getFenotipo() {
        return genes;
    }

    @Override
    public double evalua() {

        double distancia = 0d;

        for (int i = 1; i < genes.size(); i++) {
            distancia += Distancias.getDist(genes.get(i - 1), genes.get(i));
        }

        distancia += Distancias.getDist(genes.get(genes.size() - 1), 0);
        return distancia;
    }

    @Override
    public CromosomaPVC clone() {
        CromosomaPVC otro = new CromosomaPVC(false);

        for (int i = 0; i < this.genes.size(); i++) {
            otro.genes.add(this.genes.get(i));
        }
        

        otro.setAdaptacion(this.getAdaptacion());
        otro.setPuntuacion(this.getPuntuacion());

        return otro;
    }

    @Override
    public void copia(CromosomaPVC otro) {

        this.genes = new ArrayList<Integer>();

        for (Integer gen : otro.getGenes()) {
            genes.add(gen);
        }
        
        this.setAdaptacion(otro.getAdaptacion());
        this.setPuntuacion(otro.getPuntuacion());

    }

    public static boolean isCorrecto(CromosomaPVC c) {
        return isCorrecto(c.getGenes(), new HashSet<Integer>(c.getGenes().size()));
    }
    public static boolean isCorrecto(CromosomaPVC c, Set<Integer> acum) {
        return isCorrecto(c.getGenes(), acum);
    }
    
    public static boolean isCorrecto(List<Integer> c) {
        return isCorrecto(c, new HashSet<Integer>(Distancias.getSize()));
    }

    public static boolean isCorrecto(List<Integer> c, Set<Integer> acum) {
        acum.clear();
        for(Integer numero : c) {
            if (acum.contains(numero)) {
                return false;
            }
            else {
                acum.add(numero);
            }
        }
        return true;
    }

    @Override
    public String toString() {
        return genes.toString();
    }
}
